/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 *
 * http://www.gnu.org/copyleft/gpl.html
 */

package l1j.server.server;

import java.lang.reflect.Constructor;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.StringTokenizer;

import l1j.server.server.datatables.ExpTable;
import l1j.server.server.datatables.IpTable;
import l1j.server.server.datatables.ItemTable;
import l1j.server.server.datatables.LetterTable;
import l1j.server.server.datatables.NpcSpawnTable;
import l1j.server.server.datatables.NpcTable;
import l1j.server.server.datatables.PetTable;
import l1j.server.server.datatables.SkillsTable;
import l1j.server.server.datatables.SpawnTable;
import l1j.server.server.model.L1DwarfInventory;
import l1j.server.server.model.L1Inventory;
import l1j.server.server.model.L1Location;
import l1j.server.server.model.L1NpcDeleteTimer;
import l1j.server.server.model.L1Object;
import l1j.server.server.model.L1Party;
import l1j.server.server.model.L1PolyMorph;
import l1j.server.server.model.L1Spawn;
import l1j.server.server.model.L1Teleport;
import l1j.server.server.model.L1World;
import l1j.server.server.model.Instance.L1ItemInstance;
import l1j.server.server.model.Instance.L1MonsterInstance;
import l1j.server.server.model.Instance.L1NpcInstance;
import l1j.server.server.model.Instance.L1PcInstance;
import l1j.server.server.model.Instance.L1PetInstance;
import l1j.server.server.model.Instance.L1SummonInstance;
import l1j.server.server.model.Instance.L1TrapInstance;
import l1j.server.server.model.item.L1ItemId;
import l1j.server.server.model.map.L1WorldMap;
import l1j.server.server.model.skill.L1SkillId;
import l1j.server.server.model.skill.L1SkillUse;
import l1j.server.server.model.trap.L1WorldTraps;
import l1j.server.server.serverpackets.S_AddSkill;
import l1j.server.server.serverpackets.S_DeleteNewObject;
import l1j.server.server.serverpackets.S_DeleteObjectFromScreen;
import l1j.server.server.serverpackets.S_Disconnect;
import l1j.server.server.serverpackets.S_DoActionGFX;
import l1j.server.server.serverpackets.S_HPMeter;
import l1j.server.server.serverpackets.S_Invis;
import l1j.server.server.serverpackets.S_Lawful;
import l1j.server.server.serverpackets.S_Message_YN;
import l1j.server.server.serverpackets.S_OpCode_Test;
import l1j.server.server.serverpackets.S_OtherCharPacks;
import l1j.server.server.serverpackets.S_OwnCharStatus;
import l1j.server.server.serverpackets.S_ServerMessage;
import l1j.server.server.serverpackets.S_SkillBrave;
import l1j.server.server.serverpackets.S_SkillHaste;
import l1j.server.server.serverpackets.S_SkillIconGFX;
import l1j.server.server.serverpackets.S_SkillSound;
import l1j.server.server.serverpackets.S_SystemMessage;
import l1j.server.server.serverpackets.S_Weather;
import l1j.server.server.serverpackets.S_WhoAmount;
import l1j.server.server.templates.L1Item;
import l1j.server.server.templates.L1Npc;
import l1j.server.server.templates.L1Skills;
import l1j.server.server.utils.IntRange;

// Referenced classes of package l1j.server.server:
// ClientThread, Shutdown, IpTable, MobTable,
// PolyTable, IdFactory
//

public class GMCommands {
	private static Logger _log = Logger.getLogger(GMCommands.class.getName());

	boolean spawnTF = false;

	private static GMCommands _instance;

	private GMCommands() {
	}

	public static GMCommands getInstance() {
		if (_instance == null) {
			_instance = new GMCommands();
		}
		return _instance;
	}

	public void handleCommands(L1PcInstance gm, String cmdLine) {
		StringTokenizer token = new StringTokenizer(cmdLine);
		// 最初の空白までがコマンド、それ以降は空白を区切りとしたパラメータとして扱う
		String cmd = token.nextToken();
		String param = "";
		while (token.hasMoreTokens()) {
			param = new StringBuilder(param).append(token.nextToken()).append(
					' ').toString();
		}
		param = param.trim();
		try {
			// 一般プレイヤーに開放するコマンドはここに書く
			if (!gm.isMonitor() && !gm.isGm()) {
				gm.sendPackets(new S_ServerMessage(74, "コマンド" + cmd)); // \f1%0は使用できません。
				return;
			}
			// モニターに開放するコマンドはここに書く
			if (!gm.isGm()) {
				gm.sendPackets(new S_ServerMessage(74, "コマンド" + cmd)); // \f1%0は使用できません。
				return;
			}
			if (cmd.equalsIgnoreCase("help")) {
				showHelp(gm);
			} else if (cmd.equalsIgnoreCase("summon")) {
				summon(gm, param);
			} else if (cmd.equalsIgnoreCase("cleaning")) {
				deleteItem();
			} else if (cmd.equalsIgnoreCase("setting")) {
				setting(gm, param);
			} else if (cmd.equalsIgnoreCase("allrecall")) {
				allrecall(gm);
			} else if (cmd.equalsIgnoreCase("addskill")) {
				addSkill(gm);
			} else if (cmd.equalsIgnoreCase("speed")) {
				speed(gm);
			} else if (cmd.equalsIgnoreCase("level")) {
				level(gm, param);
			} else if (cmd.equalsIgnoreCase("recall")) {
				recall(gm, param);
			} else if (cmd.equalsIgnoreCase("partyrecall")) {
				partyrecall(gm, param);
			} else if (cmd.equalsIgnoreCase("move")) {
				teleportTo(gm, param);
			} else if (cmd.equalsIgnoreCase("loc")) {
				loc(gm);
			} else if (cmd.equalsIgnoreCase("death")) {
				kill(gm, param);
			} else if (cmd.equalsIgnoreCase("ress")) {
				ress(gm);
			} else if (cmd.equalsIgnoreCase("adena")) {
				adena(gm, param);
			} else if (cmd.equalsIgnoreCase("teleportto")) {
				moveToChar(gm, param);
			} else if (cmd.equalsIgnoreCase("tospawn")) { 
				tospawn(gm, param);
			} else if (cmd.equalsIgnoreCase("invisible")) {
				invisible(gm);
			} else if (cmd.equalsIgnoreCase("visible")) {
				visible(gm);
			} else if (cmd.equalsIgnoreCase("weather")) {
				changeWeather(gm, param);
			} else if (cmd.equalsIgnoreCase("gmroom")) {
				gmRoom(gm, param);
			} else if (cmd.equalsIgnoreCase("powerkick")) {
				powerkick(gm, param);
			} else if (cmd.equalsIgnoreCase("kick")) {
				kick(gm, param);
			} else if (cmd.equalsIgnoreCase("accbankick")) {
				accbankick(gm, param);
			} else if (cmd.equalsIgnoreCase("burf")) {
				burf(gm, param);
			} else if (cmd.equalsIgnoreCase("buffme")) {
				buff(gm, param, true);
			} else if (cmd.equalsIgnoreCase("buff")) {
				buff(gm, param, false);
			} else if (cmd.equalsIgnoreCase("spawn")) {
				spawn(gm, param);
			} else if (cmd.equalsIgnoreCase("npcspawn")) {
				npcSpawn(gm, param);
			} else if (cmd.equalsIgnoreCase("mobspawn")) {
				mobspawn(gm, param);
			} else if (cmd.equalsIgnoreCase("poly")) {
				polymorph(gm, param);
			} else if (cmd.equalsIgnoreCase("itemset")) {
				makeItemSet(gm, param);
			} else if (cmd.equalsIgnoreCase("item")) {
				givesItem(gm, param);
			} else if (cmd.equalsIgnoreCase("chatng")) {
				chatng(gm, param);
			} else if (cmd.equalsIgnoreCase("chat")) {
				chat(gm, param);
			} else if (cmd.equalsIgnoreCase("present")) {
				present(gm, param);
			} else if (cmd.equalsIgnoreCase("lvpresent")) {
				lvPresent(gm, param);
			} else if (cmd.equalsIgnoreCase("shutdown_now")) {
				shutdownNow();
			} else if (cmd.equalsIgnoreCase("shutdown_abort")) {
				shutdownAbort();
			} else if (cmd.equalsIgnoreCase("shutdown")) {
				shutdown(gm, param);
			} else if (cmd.equalsIgnoreCase("resettrap")) {
				resetTrap();
			} else if (cmd.equalsIgnoreCase("hometown")) {
				hometown(gm, param);
			} else if (cmd.equalsIgnoreCase("gfxid")) {
				gfxId(gm, param);
			} else if (cmd.equalsIgnoreCase("invgfxid")) {
				invGfxId(gm, param);
			} else if (cmd.equalsIgnoreCase("action")) {
				action(gm, param);
			} else if (cmd.equalsIgnoreCase("banip")) {
				banIp(gm, param);
			} else if (cmd.equalsIgnoreCase("who")) {
				who(gm, param);
			} else if (cmd.equalsIgnoreCase("skick")) {
				skick(gm, param);
			} else if (cmd.equalsIgnoreCase("desc")) {
				describe(gm);
			} else if (cmd.equalsIgnoreCase("hpbar")) {
				hpBar(gm, param);
			} else if (cmd.equalsIgnoreCase("showtrap")) {
				showTraps(gm, param);
			} else if (cmd.equalsIgnoreCase("reloadtrap")) {
				reloadTraps();
			} else if (cmd.equalsIgnoreCase("r")) {
				redo(gm, param);
			} else if (cmd.equalsIgnoreCase("f")) {
				favorite(gm, param);
			}
			// ■■■■ オペレーションコード解析用 ■■■■ ここから
			else if (cmd.equalsIgnoreCase("opcid2")) {
				opcId2(gm, param);
			} else if (cmd.equalsIgnoreCase("opcid1")) {
				opcId1(gm, param);
			} else if (cmd.equalsIgnoreCase("opcid")) {
				opcId(gm, param);
			} else if (cmd.equalsIgnoreCase("opc2")) {
				opc2(gm, param);
			} else if (cmd.equalsIgnoreCase("opc1")) {
				opc1(gm, param);
			} else if (cmd.equalsIgnoreCase("opc")) {
				opc(gm, param);
			}
			// ■■■■ オペレーションコード解析用 ■■■■ ここまで
			else {
				gm.sendPackets(new S_SystemMessage(
						"コマンド " + cmd + " は存在しません。"));
				return;
			}
			if (!cmd.equalsIgnoreCase("r")) {
				_lastCmd = cmdLine;
			}
			_log.info(gm.getName() + "が." + cmdLine + "コマンドを使用しました。");
		} catch (Exception e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
		}
	}

	private void setting(L1PcInstance pc, String s) {
		try {
			StringTokenizer stringtokenizer = new StringTokenizer(s); // 実行文を取得

			String char_name = stringtokenizer.nextToken(); // 次文字列を取得

			String param = stringtokenizer.nextToken(); // 次文字列を取得

			String value = stringtokenizer.nextToken(); // 次文字列を取得

			int data = Integer.parseInt(value); // 文字列を数値に変換

			L1PcInstance target = getPcForName(char_name);

			pc.sendPackets(new S_SystemMessage("キャラクター：" + char_name + "変更項目："
					+ param + "変更値：" + value));

			if (param.equalsIgnoreCase("HP")) {
				target.addBaseMaxHp((short) (data - target.getBaseMaxHp()));
				target.setCurrentHpDirect(target.getMaxHp());
				target.save(); // DBにキャラクター情報を書き込む
				target.sendPackets(new S_SystemMessage("あなたのHPが"
						+ target.getBaseMaxHp() + "に変更されました。"));
				target.sendPackets(new S_OwnCharStatus(target));
			} else if (param.equalsIgnoreCase("MP")) {
				target.addBaseMaxMp((short) (data - target.getBaseMaxMp()));
				target.setCurrentMpDirect(target.getMaxMp());
				target.save(); // DBにキャラクター情報を書き込む
				target.sendPackets(new S_SystemMessage("あなたのMPが"
						+ target.getBaseMaxMp() + "に変更されました。"));
				target.sendPackets(new S_OwnCharStatus(target));
			} else if (param.equalsIgnoreCase("AC")) {
				target.addAc((byte) (data - target.getAc()));
				target.sendPackets(new S_SystemMessage("あなたのACが"
						+ target.getAc() + "に変更されました。"));
				target.sendPackets(new S_OwnCharStatus(target));
			} else if (param.equalsIgnoreCase("GM")) {
				if (data > 200) {
					data = 200;
				}
				target.setAccessLevel((short) data);
				target.save(); // DBにキャラクター情報を書き込む
				target
						.sendPackets(new S_SystemMessage(
								"リスタートすれば、GMに昇格されています。"));
				target.sendPackets(new S_OwnCharStatus(target));
			} else if (param.equalsIgnoreCase("LAWFUL")) {
				target.setLawful(data);
				target.save(); // DBにキャラクター情報を書き込む
				target.sendPackets(new S_SystemMessage("あなたのLAWFULが"
						+ target.getLawful() + "に変更されました。"));
				target.sendPackets(new S_OwnCharStatus(target));
				S_Lawful s_lawful = new S_Lawful(target.getId(), target
						.getLawful());
				target.sendPackets(s_lawful);
				target.broadcastPacket(s_lawful);
			} else if (param.equalsIgnoreCase("KARMA")) {
				target.setKarma(data);
				target.save(); // DBにキャラクター情報を書き込む
				target.sendPackets(new S_SystemMessage("あなたのカルマが"
						+ target.getKarma() + "に変更されました。"));
			} else if (param.equalsIgnoreCase("MR")) {
				target.addMr((short) (data - target.getMr()));
				target.sendPackets(new S_SystemMessage("あなたのMRが"
						+ target.getMr() + "に変更されました。"));
				target.sendPackets(new S_OwnCharStatus(target));
			} else if (param.equalsIgnoreCase("HIT")) {
				target.addHitup((short) (data - target.getHitup()));
				target.sendPackets(new S_SystemMessage("あなたの命中率補正が"
						+ target.getHitup() + "に変更されました。"));
				target.sendPackets(new S_OwnCharStatus(target));
			} else if (param.equalsIgnoreCase("DMG")) {
				target.addDmgup((short) (data - target.getDmgup()));
				target.sendPackets(new S_SystemMessage("あなたの追加ダメージ追加が"
						+ target.getDmgup() + "に変更されました。"));
				target.sendPackets(new S_OwnCharStatus(target));
			}

		} catch (Exception e) {
			pc
					.sendPackets(new S_SystemMessage(
							".setting キャラクター名 [ HP or MP or AC or MR or HIT or DMG or GM or LAWFUL or KARMA] 変更値 と入力して下さい。"));
		}
	}

	private void showHelp(L1PcInstance pc) {
		pc.sendPackets(new S_SystemMessage(
				".setting .summon .cleaning .allrecall .addskill .speed .level .recall .partyrecall .move .loc .death .ress .adena .teleportto .invisible .visible .weather .gmroom .powerkick .accbankick .kick .burf .buff .spawn .npcspawn .mobspawn .poly .item .chatng .chat .who .present .lvpresent .hometown .shutdown .shutdown_now .shutdown_abort .resettrap .gfxid .invgfxid .action .banip .who .skick .desc .r"));
	}

	private void summon(L1PcInstance pc, String param) {
		try {
			StringTokenizer tok = new StringTokenizer(param);
			String nameid = tok.nextToken();
			int npcid = 0;
			try {
				npcid = Integer.parseInt(nameid);
			} catch (NumberFormatException e) {
				npcid = NpcTable.getInstance().findNpcIdByNameWithoutSpace(
						nameid);
				if (npcid == 0) {
					pc.sendPackets(new S_SystemMessage("該当NPCが見つかりません。"));
					return;
				}
			}
			int count = 1;
			if (tok.hasMoreTokens()) {
				count = Integer.parseInt(tok.nextToken());
			}
			L1Npc npc = NpcTable.getInstance().getTemplate(npcid);
			for (int i = 0; i < count; i++) {
				L1SummonInstance summonInst = new L1SummonInstance(npc, pc);
				summonInst.setPetcost(0);
			}
			nameid = NpcTable.getInstance().getTemplate(npcid).get_name();
			pc.sendPackets(new S_SystemMessage(nameid + "(ID:" + npcid + ") ("
					+ count + ") を召還しました。"));
		} catch (Exception e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
			pc.sendPackets(new S_SystemMessage(
					".summon npcid|name [数] と入力して下さい。"));
		}
	}

	private void addSkill(L1PcInstance pc) {
		try {
			int cnt = 0; // ループカウンタ
			String skill_name = ""; // スキル名
			int skill_id = 0; // スキルID

			int object_id = pc.getId(); // キャラクタのobjectidを取得
			pc.sendPackets(new S_SkillSound(object_id, '\343')); // 魔法習得の効果音を鳴らす
			pc.broadcastPacket(new S_SkillSound(object_id, '\343'));

			if (pc.isCrown()) {
				pc.sendPackets(new S_AddSkill(255, 255, 0, 0, 0, 0, 0, 0, 0, 0,
						0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0));
				for (cnt = 1; cnt <= 16; cnt++) // LV1~2魔法
				{
					L1Skills l1skills = SkillsTable.getInstance().getTemplate(
							cnt); // スキル情報を取得
					skill_name = l1skills.getName();
					skill_id = l1skills.getSkillId();
					SkillsTable.getInstance().spellMastery(object_id, skill_id,
							skill_name, 0, 0); // DBに登録
				}
				for (cnt = 113; cnt <= 120; cnt++) // プリ魔法
				{
					L1Skills l1skills = SkillsTable.getInstance().getTemplate(
							cnt); // スキル情報を取得
					skill_name = l1skills.getName();
					skill_id = l1skills.getSkillId();
					SkillsTable.getInstance().spellMastery(object_id, skill_id,
							skill_name, 0, 0); // DBに登録
				}
			} else if (pc.isKnight()) {
				pc.sendPackets(new S_AddSkill(255, 0, 0, 0, 0, 0, 0, 0, 0, 0,
						192, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
				for (cnt = 1; cnt <= 8; cnt++) // LV1魔法
				{
					L1Skills l1skills = SkillsTable.getInstance().getTemplate(
							cnt); // スキル情報を取得
					skill_name = l1skills.getName();
					skill_id = l1skills.getSkillId();
					SkillsTable.getInstance().spellMastery(object_id, skill_id,
							skill_name, 0, 0); // DBに登録
				}
				for (cnt = 87; cnt <= 91; cnt++) // ナイト魔法
				{
					L1Skills l1skills = SkillsTable.getInstance().getTemplate(
							cnt); // スキル情報を取得
					skill_name = l1skills.getName();
					skill_id = l1skills.getSkillId();
					SkillsTable.getInstance().spellMastery(object_id, skill_id,
							skill_name, 0, 0); // DBに登録
				}
			} else if (pc.isElf()) {
				pc.sendPackets(new S_AddSkill(255, 255, 127, 255, 255, 255, 0,
						0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 3, 255, 255, 255, 255,
						0, 0));
				for (cnt = 1; cnt <= 48; cnt++) // LV1~6魔法
				{
					L1Skills l1skills = SkillsTable.getInstance().getTemplate(
							cnt); // スキル情報を取得
					skill_name = l1skills.getName();
					skill_id = l1skills.getSkillId();
					SkillsTable.getInstance().spellMastery(object_id, skill_id,
							skill_name, 0, 0); // DBに登録
				}
				for (cnt = 129; cnt <= 176; cnt++) // エルフ魔法
				{
					L1Skills l1skills = SkillsTable.getInstance().getTemplate(
							cnt); // スキル情報を取得
					skill_name = l1skills.getName();
					skill_id = l1skills.getSkillId();
					SkillsTable.getInstance().spellMastery(object_id, skill_id,
							skill_name, 0, 0); // DBに登録
				}
			} else if (pc.isWizard()) {
				pc.sendPackets(new S_AddSkill(255, 255, 127, 255, 255, 255,
						255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
						0, 0));
				for (cnt = 1; cnt <= 80; cnt++) // LV1~10魔法
				{
					L1Skills l1skills = SkillsTable.getInstance().getTemplate(
							cnt); // スキル情報を取得
					skill_name = l1skills.getName();
					skill_id = l1skills.getSkillId();
					SkillsTable.getInstance().spellMastery(object_id, skill_id,
							skill_name, 0, 0); // DBに登録
				}
			} else if (pc.isDarkelf()) {
				pc.sendPackets(new S_AddSkill(255, 255, 0, 0, 0, 0, 0, 0, 0, 0,
						0, 0, 255, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
				for (cnt = 1; cnt <= 16; cnt++) // LV1~2魔法
				{
					L1Skills l1skills = SkillsTable.getInstance().getTemplate(
							cnt); // スキル情報を取得
					skill_name = l1skills.getName();
					skill_id = l1skills.getSkillId();
					SkillsTable.getInstance().spellMastery(object_id, skill_id,
							skill_name, 0, 0); // DBに登録
				}
				for (cnt = 97; cnt <= 111; cnt++) // DE魔法
				{
					L1Skills l1skills = SkillsTable.getInstance().getTemplate(
							cnt); // スキル情報を取得
					skill_name = l1skills.getName();
					skill_id = l1skills.getSkillId();
					SkillsTable.getInstance().spellMastery(object_id, skill_id,
							skill_name, 0, 0); // DBに登録
				}
			}
		} catch (Exception e) {
			pc.sendPackets(new S_SystemMessage(

			".addskill コマンドエラー"));
		}
	}

	private void speed(L1PcInstance pc) {
		int objectId = pc.getId();
		try {
			int time = 3600 * 1000;

			// ブレイブ付与
			pc.setSkillEffect(L1SkillId.STATUS_BRAVE, time);

			pc.sendPackets(new S_SkillBrave(objectId, 1, 3600));
			pc.sendPackets(new S_SkillSound(objectId, 751));
			pc.broadcastPacket(new S_SkillSound(objectId, 751));
			pc.setBraveSpeed(1);

			// ヘイスト付与
			pc.setSkillEffect(L1SkillId.STATUS_HASTE, time);

			pc.sendPackets(new S_SkillHaste(objectId, 1, 3600));
			pc.sendPackets(new S_SkillSound(objectId, 191));
			pc.broadcastPacket(new S_SkillSound(objectId, 191));
			pc.setMoveSpeed(1);

		} catch (Exception e) {
			pc.sendPackets(new S_SystemMessage(".speed コマンドエラー"));
		}
	}

	private void level(L1PcInstance pc, String param) {
		try {
			StringTokenizer tok = new StringTokenizer(param);
			int level = Integer.parseInt(tok.nextToken());
			if (level == pc.getLevel()) {
				return;
			}
			if (!IntRange.includes(level, 1, 99)) {
				pc.sendPackets(new S_SystemMessage("1-99の範囲で指定してください"));
				return;
			}
			pc.setExp(ExpTable.getExpByLevel(level));
		} catch (Exception e) {
			pc.sendPackets(new S_SystemMessage(".level lv と入力して下さい"));
		}
	}

	private void loc(L1PcInstance pc) {
		try {
			int locx = pc.getX();
			int locy = pc.getY();
			short mapid = pc.getMapId();
			int gab = L1WorldMap.getInstance().getMap(mapid).getOriginalTile(
					locx, locy);
			pc.sendPackets(new S_SystemMessage((new StringBuilder()).append(
					"座標 (").append(locx).append(", ").append(locy).append(", ")
					.append(mapid).append(") ").append(gab).toString()));
		} catch (Exception e) {
		}
	}

	private void adena(L1PcInstance pc, String param) {
		try {
			StringTokenizer stringtokenizer = new StringTokenizer(param);
			String para1 = stringtokenizer.nextToken();
			int count = Integer.parseInt(para1);

			L1ItemInstance adena = pc.getInventory().storeItem(L1ItemId.ADENA,
					count);
			if (adena != null) {
				pc.sendPackets(new S_SystemMessage((new StringBuilder())
						.append(count).append("アデナを生成しました。").toString()));
			}
		} catch (Exception e) {
			pc.sendPackets(new S_SystemMessage((new StringBuilder()).append(
					".adena アデナ数 と入力して下さい。").toString()));
		}
	}

	private void moveToChar(L1PcInstance gm, String param) {
		try {
			StringTokenizer tokenizer = new StringTokenizer(param);
			String pcName = tokenizer.nextToken();

			L1PcInstance target = getPcForName(pcName);

			if (target != null) {
				L1Teleport.teleport(gm, target.getX(), target.getY(), target
						.getMapId(), 5, false);
				gm.sendPackets(new S_SystemMessage((new StringBuilder())
						.append(pcName).append("さんの元へ移動しました。").toString()));
			} else {
				gm.sendPackets(new S_SystemMessage((new StringBuilder())
						.append(pcName).append("さんはいません。").toString()));
			}
		} catch (Exception exception) {
			gm
					.sendPackets(new S_SystemMessage(
							".teleportto キャラクター名 と入力して下さい。"));
		}
	}

	private void resetTrap() {
		L1WorldTraps.getInstance().resetAllTraps();
	}

	private void hometown(L1PcInstance gm, String param) {
		try {
			StringTokenizer st = new StringTokenizer(param);
			String para1 = st.nextToken();
			if (para1.equalsIgnoreCase("daily")) {
				HomeTownTimeController.getInstance().dailyProc();
			} else if (para1.equalsIgnoreCase("monthly")) {
				HomeTownTimeController.getInstance().monthlyProc();
			} else {
				throw new Exception();
			}
		} catch (Exception e) {
			gm.sendPackets(new S_SystemMessage(
					".hometown daily|monthly と入力して下さい。"));
		}

	}

	private void opc(L1PcInstance gm, String param) {
		try {
			gm.sendPackets(new S_OpCode_Test(Integer.parseInt(param), 0, gm));
		} catch (Exception ex) {
			try {
				gm.sendPackets(new S_SystemMessage(
						(new S_OpCode_Test(0, 0, gm)).getInfo()));
			} catch (Exception ex2) {
				gm
						.sendPackets(new S_SystemMessage(
								"S_OpCode_Testでエラーが発生しました。"));
			}
		}
	}

	private void opc1(L1PcInstance gm, String param) {
		try {
			gm.sendPackets(new S_OpCode_Test(Integer.parseInt(param), 1, gm));
		} catch (Exception ex) {
			try {
				gm.sendPackets(new S_SystemMessage(
						(new S_OpCode_Test(0, 1, gm)).getInfo()));
			} catch (Exception ex2) {
				gm
						.sendPackets(new S_SystemMessage(
								"S_OpCode_Testでエラーが発生しました。"));
			}
		}
	}

	private void opc2(L1PcInstance gm, String param) {
		try {
			gm.sendPackets(new S_OpCode_Test(Integer.parseInt(param), 2, gm));
		} catch (Exception ex) {
			try {
				gm.sendPackets(new S_SystemMessage(
						(new S_OpCode_Test(0, 2, gm)).getInfo()));
			} catch (Exception ex2) {
				gm
						.sendPackets(new S_SystemMessage(
								"S_OpCode_Testでエラーが発生しました。"));
			}
		}
	}

	private void opcId(L1PcInstance gm, String param) {
		try {
			gm.sendPackets(new S_SystemMessage((new S_OpCode_Test(Integer
					.parseInt(param), 0, gm)).getCode()));
		} catch (Exception ex) {
			try {
				gm.sendPackets(new S_SystemMessage(
						(new S_OpCode_Test(0, 0, gm)).getCodeList()));
			} catch (Exception ex2) {
				gm
						.sendPackets(new S_SystemMessage(
								"S_OpCode_Testでエラーが発生しました。"));
			}
		}
	}

	private void opcId1(L1PcInstance gm, String param) {
		try {
			gm.sendPackets(new S_SystemMessage((new S_OpCode_Test(Integer
					.parseInt(param), 1, gm)).getCode()));
		} catch (Exception ex) {
			try {
				gm.sendPackets(new S_SystemMessage(
						(new S_OpCode_Test(0, 1, gm)).getCodeList()));
			} catch (Exception ex2) {
				gm
						.sendPackets(new S_SystemMessage(
								"S_OpCode_Testでエラーが発生しました。"));
			}
		}
	}

	private void opcId2(L1PcInstance gm, String param) {
		try {
			gm.sendPackets(new S_SystemMessage((new S_OpCode_Test(Integer
					.parseInt(param), 2, gm)).getCode()));
		} catch (Exception ex) {
			try {
				gm.sendPackets(new S_SystemMessage(
						(new S_OpCode_Test(0, 2, gm)).getCodeList()));
			} catch (Exception ex2) {
				gm
						.sendPackets(new S_SystemMessage(
								"S_OpCode_Testでエラーが発生しました。"));
			}
		}
	}

	private void shutdownAbort() {
		GameServer.getInstance().abortShutdown();
	}

	private void shutdownNow() {
		GameServer.getInstance().shutdown();
	}

	private void shutdown(L1PcInstance gm, String params) {
		try {
			int sec = 0;
			StringTokenizer st = new StringTokenizer(params);
			if (st.hasMoreTokens()) {
				String param1 = st.nextToken();
				sec = Integer.parseInt(param1, 10);
			}
			if (sec < 5) {
				sec = 5;
			}
			GameServer.getInstance().shutdownWithCountdown(sec);
		} catch (Exception e) {
			gm.sendPackets(new S_SystemMessage(".shutdown [sec] と入力して下さい。"));
		}
	}

	private void mobspawn(L1PcInstance gm, String param) {
		try {
			StringTokenizer stringtokenizer = new StringTokenizer(param);
			String s24 = stringtokenizer.nextToken();
			int i2 = Integer.parseInt(s24);
			L1Npc l1npc1 = NpcTable.getInstance().getTemplate(i2);
			if (l1npc1 != null) {
				String npcImpl = l1npc1.getImpl();
				if (npcImpl.equals("L1Monster")) {
					NpcTable.getInstance().storeSpawn(gm, l1npc1, 20);
					mobspawn(gm, i2, 0, false);
					gm.sendPackets(new S_SystemMessage((new StringBuilder())
							.append(l1npc1.get_name()).append(" (").append(i2)
							.append(")  insert spawnlist").toString()));
				} else {
					gm.sendPackets(new S_SystemMessage("モンスターではありません。"));
				}
			}
		} catch (Exception e) {
			gm.sendPackets(new S_SystemMessage(".mobspawn NPCID と入力して下さい。"));
		}
	}

	private void npcSpawn(L1PcInstance gm, String param) {
		try {
			StringTokenizer stringtokenizer = new StringTokenizer(param);
			String s23 = stringtokenizer.nextToken();
			int l1 = Integer.parseInt(s23);
			L1Npc l1npc = NpcTable.getInstance().getTemplate(l1);
			if (l1npc != null) {
				String npc_type = l1npc.getImpl();
				if (npc_type.equals("L1Monster")) {
					gm.sendPackets(new S_SystemMessage("NPCではありません。"));
				} else {
					NpcSpawnTable.getInstance().storeSpawn(gm, l1npc, 1);
					mobspawn(gm, l1, 0, false);
					gm.sendPackets(new S_SystemMessage((new StringBuilder())
							.append(l1npc.get_name()).append(" (").append(l1)
							.append(")  insert spawnlist").toString()));
				}
			}
		} catch (Exception e) {
			gm.sendPackets(new S_SystemMessage(".npcspawn NPCID と入力して下さい。"));
		}
	}

	private void spawn(L1PcInstance gm, String param) {
		try {
			StringTokenizer tok = new StringTokenizer(param);
			String nameid = tok.nextToken();
			int count = 1;
			if (tok.hasMoreTokens()) {
				count = Integer.parseInt(tok.nextToken());
			}
			int randomrange = 0;
			if (tok.hasMoreTokens()) {
				randomrange = Integer.parseInt(tok.nextToken(), 10);
			}
			int npcid = 0;
			try {
				npcid = Integer.parseInt(nameid);
			} catch (NumberFormatException e) {
				npcid = NpcTable.getInstance().findNpcIdByNameWithoutSpace(
						nameid);
				if (npcid == 0) {
					gm.sendPackets(new S_SystemMessage("該当NPCが見つかりません。"));
					return;
				}
			}
			spawnTF = true; // .spawn 使用
			for (int k3 = 0; k3 < count; k3++) {
				mobspawn(gm, npcid, randomrange, false);
			}
			nameid = NpcTable.getInstance().getTemplate(npcid).get_name();
			gm.sendPackets(new S_SystemMessage(nameid + "(" + npcid + ") ("
					+ count + ") を召還しました。 (範囲:" + randomrange + ")"));
			spawnTF = false;
		} catch (Exception e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
			gm.sendPackets(new S_SystemMessage(
					".spawn npcid|name [数] [範囲] と入力して下さい。"));
		}
	}

	private void changeWeather(L1PcInstance gm, String param) {
		try {
			StringTokenizer stringtokenizer = new StringTokenizer(param);
			String s27 = stringtokenizer.nextToken();
			int weather = Integer.parseInt(s27);
			L1World world = L1World.getInstance();
			world.setWeather(weather);
			L1World.getInstance().broadcastPacketToAll(new S_Weather(weather));
		} catch (Exception e) {
			gm.sendPackets(new S_SystemMessage(".weather 0～3、16～19 と入力して下さい。"));
		}
	}

	private void visible(L1PcInstance gm) {
		try {
			gm.setGmInvis(false);
			gm.sendPackets(new S_Invis(gm.getId(), 0));
			// pc.broadcastPacket(new S_Invis(pc.get_objectId(),
			// 0));
			gm.broadcastPacket(new S_OtherCharPacks(gm));
			gm.sendPackets(new S_SystemMessage("透明状態を解除しました。"));
		} catch (Exception e) {
			gm.sendPackets(new S_SystemMessage(".visible コマンドエラー"));
		}
	}

	private void invisible(L1PcInstance gm) {
		try {
			gm.setGmInvis(true);
			gm.sendPackets(new S_Invis(gm.getId(), 1));
			// pc.broadcastPacket(new S_Invis(pc.get_objectId(),
			// 1));
			gm.broadcastPacket(new S_DeleteObjectFromScreen(gm));
			gm.sendPackets(new S_SystemMessage("透明状態になりました。"));

		} catch (Exception e) {
			gm.sendPackets(new S_SystemMessage(".invisible コマンドエラー"));
		}
	}

	private void deleteItem() {
		for (L1Object l1object : L1World.getInstance().getObject()) {
			if (l1object instanceof L1ItemInstance) {
				L1ItemInstance l1iteminstance = (L1ItemInstance) l1object;
				if (l1iteminstance.getX() == 0 && l1iteminstance.getY() == 0) { // 地面上のアイテムではなく、誰かの所有物
					continue;
				}

				ArrayList<L1PcInstance> players = L1World.getInstance()
						.getVisiblePlayer(l1iteminstance, 0);
				if (0 == players.size()) {
					L1Inventory groundInventory = L1World.getInstance()
							.getInventory(l1iteminstance.getX(),
									l1iteminstance.getY(),
									l1iteminstance.getMapId());
					if (l1iteminstance.getItem().getItemId() == 40314 || // ペットのアミュレット
							l1iteminstance.getItem().getItemId() == 40316) {
						PetTable pettable = new PetTable();
						pettable.deletePet(l1iteminstance.getId());
					}
					if (l1iteminstance.getItem().getItemId() >= 49016 // 便箋
							&& l1iteminstance.getItem().getItemId() <= 49025) {
						LetterTable lettertable = new LetterTable();
						lettertable.deleteLetter(l1iteminstance.getId());
					}
					groundInventory.deleteItem(l1iteminstance);
					L1World.getInstance().removeVisibleObject(l1iteminstance);
					L1World.getInstance().removeObject(l1iteminstance);
				}
			}
		}
		L1World.getInstance().broadcastServerMessage(
				"ワールドマップ上のアイテムがGMにより削除されました。");
	}

	private void recall(L1PcInstance gm, String param) {
		try {
			StringTokenizer tokenizer = new StringTokenizer(param);
			String pcName = tokenizer.nextToken();

			L1PcInstance target = getPcForName(pcName);
			if (target != null) {
				recallnow(gm, target);
			} else {
				gm.sendPackets(new S_SystemMessage("そのようなキャラクターはいません。"));
			}
		} catch (Exception e) {
			gm.sendPackets(new S_SystemMessage(".recall キャラクター名 と入力して下さい。"));
		}
	}

	private void allrecall(L1PcInstance gm) {
		try {
			for (L1PcInstance pc : L1World.getInstance().getAllPlayers()) {
				if (pc.getAccessLevel() != 200) {
					recallnow(gm, pc);
				}
			}
		} catch (Exception e) {
			gm.sendPackets(new S_SystemMessage(".allrecall コマンドエラー"));
		}

	}

	private void partyrecall(L1PcInstance pc, String param) {
		StringTokenizer tokenizer = new StringTokenizer(param);
		String pcName = tokenizer.nextToken();

		L1PcInstance target = getPcForName(pcName);
		if (target != null) {
			L1Party party = target.getParty();
			if (party != null) {
				int x = pc.getX();
				int y = pc.getY() + 2;
				short map = pc.getMapId();
				L1PcInstance[] players = party.getMembers();
				for (L1PcInstance pc2 : players) {
					try {
						L1Teleport.teleport(pc2, x, y, map, 5, true);
						pc2
								.sendPackets(new S_SystemMessage(
										"ゲームマスターに召還されました。"));
					} catch (Exception e) {
						_log.log(Level.SEVERE, "", e);
					}
				}
			} else {
				pc.sendPackets(new S_SystemMessage("パーティメンバーではありません。"));
			}
		} else {
			pc.sendPackets(new S_SystemMessage("そのようなキャラクターはいません。"));
		}
	}

	private void recallnow(L1PcInstance gm, L1PcInstance target) {
		try {
			L1Teleport.teleportToTargetFront(target, gm, 2);
			gm.sendPackets(new S_SystemMessage((new StringBuilder()).append(
					target.getName()).append("さんを召還しました。").toString()));
			target.sendPackets(new S_SystemMessage("ゲームマスターに召還されました。"));
		} catch (Exception e) {
			_log.log(Level.SEVERE, "", e);
		}
	}

	private void polymorph(L1PcInstance gm, String param) {
		try {
			boolean flag = false;
			StringTokenizer stringtokenizer = new StringTokenizer(param);
			String name = stringtokenizer.nextToken();
			String s2 = stringtokenizer.nextToken();
			L1PcInstance pc = getPcForName(name);

			if (pc != null) {
				S_SystemMessage s_systemmessage1;
				try {
					flag = true;

					int j = Integer.parseInt(s2);
					L1PolyMorph.doPoly(pc, j, 7200);
				} catch (Exception exception) {
					s_systemmessage1 = new S_SystemMessage(
							".poly キャラクター名 グラフィックID と入力して下さい。");
					gm.sendPackets(s_systemmessage1);
				}
			}

			if (!flag) {
				S_ServerMessage s_servermessage = new S_ServerMessage(73, name);
				gm.sendPackets(s_servermessage);
			}
		} catch (Exception e) {
			gm.sendPackets(new S_SystemMessage(
					".poly キャラクター名 グラフィックID と入力して下さい。"));
		}
	}

	private void chatng(L1PcInstance gm, String param) {
		try {
			StringTokenizer stringtokenizer = new StringTokenizer(param);
			String name = stringtokenizer.nextToken();
			L1PcInstance pc = getPcForName(name);
			String s2 = stringtokenizer.nextToken();
			int time = Integer.parseInt(s2);
			if (pc != null) {
				pc.setSkillEffect(L1SkillId.STATUS_CHAT_PROHIBITED,
						time * 60 * 1000);
				pc.sendPackets(new S_SkillIconGFX(36, time * 60));
				pc.sendPackets(new S_ServerMessage(286, String.valueOf(time))); // \f3ゲームに適合しない行動であるため、今後%0分間チャットを禁じます。
				gm.sendPackets(new S_ServerMessage(287, name)); // %0のチャットを禁じました。
			}
		} catch (Exception e) {
			gm.sendPackets(new S_SystemMessage(
					".chatng キャラクター名 時間（分） と入力して下さい。"));
		}
	}

	private void chat(L1PcInstance gm, String param) {
		try {
			StringTokenizer st = new StringTokenizer(param);
			if (st.hasMoreTokens()) {
				String flag = st.nextToken();
				String msg;
				if (flag.compareToIgnoreCase("on") == 0) {
					L1World.getInstance().set_worldChatElabled(true);
					msg = "ワールドチャットを有効にしました。";
				} else if (flag.compareToIgnoreCase("off") == 0) {
					L1World.getInstance().set_worldChatElabled(false);
					msg = "ワールドチャットを停止しました。";
				} else {
					throw new Exception();
				}
				gm.sendPackets(new S_SystemMessage(msg));
			} else {
				String msg;
				if (L1World.getInstance().isWorldChatElabled()) {
					msg = "現在ワールドチャットは有効です。.chat off で停止できます。";
				} else {
					msg = "現在ワールドチャットは停止しています。.chat on で有効にできます。";
				}
				gm.sendPackets(new S_SystemMessage(msg));
			}
		} catch (Exception e) {
			gm.sendPackets(new S_SystemMessage(".chat [on|off]"));
		}
	}

	private void teleportTo(L1PcInstance pc, String param) {
		try {
			StringTokenizer st = new StringTokenizer(param);
			int locx = Integer.parseInt(st.nextToken());
			int locy = Integer.parseInt(st.nextToken());
			short mapid;
			if (st.hasMoreTokens()) {
				mapid = Short.parseShort(st.nextToken());
			} else {
				mapid = pc.getMapId();
			}
			L1Teleport.teleport(pc, locx, locy, mapid, 5, false);
			pc.sendPackets(new S_SystemMessage("座標 " + locx + ", " + locy
					+ ", " + mapid + "に移動しました。"));
		} catch (Exception e) {
			pc.sendPackets(new S_SystemMessage(
					".move X座標 Y座標 [マップID] と入力して下さい。"));
		}
	}

	private int _spawnId = 0;
	
	/** GMコマンド.tospawn から呼ばれる。指定したspawnidの座標へ飛ぶ。 */
	private void tospawn(L1PcInstance gm, String param) {
		try {
			if (param.isEmpty() || param.equals("+")) {
				_spawnId++;
			} else if (param.equals("-")) {
				_spawnId--;
			} else {
				StringTokenizer st = new StringTokenizer(param);
				_spawnId = Integer.parseInt(st.nextToken());
			}
			L1Spawn spawn = NpcSpawnTable.getInstance().getTemplate(_spawnId);
			if (spawn == null) {
				spawn = SpawnTable.getInstance().getTemplate(_spawnId);
			}
			if (spawn != null) {
				L1Teleport.teleport(gm, spawn.getLocX(),
						spawn.getLocY(), spawn.getMapId(), 5, false);
				gm.sendPackets(new S_SystemMessage(
						"spawnid(" + _spawnId + ")の元へ飛びます"));
			} else {
				gm.sendPackets(new S_SystemMessage(
						"spawnid(" + _spawnId + ")は見つかりません"));
			}
		} catch (Exception exception) {
			gm.sendPackets(new S_SystemMessage(
					"Error    usage:.tospawn spawnid|+|-"));
		}
	}

	private void makeItemSet(L1PcInstance gm, String param) {
		try {
			String name = new StringTokenizer(param).nextToken();
			List<ItemSetItem> list = GMCommandsConfig.ITEM_SETS.get(name);
			if (list == null) {
				gm.sendPackets(new S_SystemMessage(name + " 未定義のセットです"));
				return;
			}
			for (ItemSetItem item : list) {
				L1Item temp = ItemTable.getInstance().getTemplate(item.getId());
				if (!temp.isStackable() && 0 != item.getEnchant()) {
					for (int i = 0; i < item.getAmount(); i++) {
						L1ItemInstance inst = ItemTable.getInstance()
								.createItem(item.getId());
						inst.setEnchantLevel(item.getEnchant());
						gm.getInventory().storeItem(inst);
					}
				} else {
					gm.getInventory().storeItem(item.getId(), item.getAmount());
				}
			}
		} catch (Exception e) {
			gm.sendPackets(new S_SystemMessage(".itemset セット名 と入力してください。"));
		}
	}

	private void givesItem(L1PcInstance gm, String param) {
		try {
			StringTokenizer st = new StringTokenizer(param);
			String nameid = st.nextToken();
			int count = 1;
			if (st.hasMoreTokens()) {
				count = Integer.parseInt(st.nextToken());
			}
			int enchant = 0;
			if (st.hasMoreTokens()) {
				enchant = Integer.parseInt(st.nextToken());
			}
			int itemid = 0;
			try {
				itemid = Integer.parseInt(nameid);
			} catch (NumberFormatException e) {
				itemid = ItemTable.getInstance().findItemIdByNameWithoutSpace(
						nameid);
				if (itemid == 0) {
					gm.sendPackets(new S_SystemMessage("該当アイテムが見つかりません。"));
					return;
				}
			}
			L1Item temp = ItemTable.getInstance().getTemplate(itemid);
			if (temp != null) {
				if (temp.isStackable()) {
					L1ItemInstance item = ItemTable.getInstance().createItem(
							itemid);
					item.setEnchantLevel(0);
					item.setCount(count);
					if (gm.getInventory().checkAddItem(item, count) == L1Inventory.OK) {
						gm.getInventory().storeItem(item);
						gm.sendPackets(new S_SystemMessage(item.getLogName()
								+ "を手に入れました。 (ID:" + itemid + ")"));
					}
				} else {
					L1ItemInstance item = null;
					int createCount;
					for (createCount = 0; createCount < count; createCount++) {
						item = ItemTable.getInstance().createItem(itemid);
						item.setEnchantLevel(enchant);
						if (gm.getInventory().checkAddItem(item, 1) == L1Inventory.OK) {
							gm.getInventory().storeItem(item);
						} else {
							break;
						}
					}
					if (createCount > 0) {
						gm.sendPackets(new S_SystemMessage(item.getLogName()
								+ "を手に入れました。 (ID:" + itemid + ")"));
					}
				}
			} else {
				gm.sendPackets(new S_SystemMessage("指定IDのアイテムは存在しません"));
			}
		} catch (Exception e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
			gm.sendPackets(new S_SystemMessage(
					".item itemid|name [個数] [エンチャント数] と入力して下さい。"));
		}
	}

	private void present(L1PcInstance gm, String param) {
		try {
			StringTokenizer st = new StringTokenizer(param);
			String account = st.nextToken();
			int itemid = Integer.parseInt(st.nextToken(), 10);
			int enchant = Integer.parseInt(st.nextToken(), 10);
			int count = Integer.parseInt(st.nextToken(), 10);

			L1Item temp = ItemTable.getInstance().getTemplate(itemid);
			if (temp == null) {
				gm.sendPackets(new S_SystemMessage("存在しないアイテムIDです。"));
				return;
			}

			L1DwarfInventory.present(account, itemid, enchant, count);
			gm.sendPackets(new S_SystemMessage(temp.getName() + "を" + count
					+ "個プレゼントしました。"));
		} catch (Exception e) {
			gm
					.sendPackets(new S_SystemMessage(
							".present アカウント名 アイテムID エンチャント数 アイテム数 と入力してください。（アカウント名=*で全て）"));
		}
	}

	private void lvPresent(L1PcInstance gm, String param) {
		try {
			StringTokenizer st = new StringTokenizer(param);
			int minlvl = Integer.parseInt(st.nextToken(), 10);
			int maxlvl = Integer.parseInt(st.nextToken(), 10);
			int itemid = Integer.parseInt(st.nextToken(), 10);
			int enchant = Integer.parseInt(st.nextToken(), 10);
			int count = Integer.parseInt(st.nextToken(), 10);

			L1Item temp = ItemTable.getInstance().getTemplate(itemid);
			if (temp == null) {
				gm.sendPackets(new S_SystemMessage("存在しないアイテムIDです。"));
				return;
			}

			L1DwarfInventory.present(minlvl, maxlvl, itemid, enchant, count);
			gm.sendPackets(new S_SystemMessage(temp.getName() + "を" + count
					+ "個プレゼントしました。(Lv" + minlvl + "～" + maxlvl + ")"));
		} catch (Exception e) {
			gm
					.sendPackets(new S_SystemMessage(
							".lvpresent minlvl maxlvl アイテムID エンチャント数 アイテム数 と入力してください。"));
		}
	}

	private void kill(L1PcInstance gm, String param) {
		try {
			StringTokenizer tokenizer = new StringTokenizer(param);
			String pcName = tokenizer.nextToken();

			L1PcInstance target = getPcForName(pcName);
			if (target != null) {
				target.setCurrentHp(0);
				target.death(null);
			}
		} catch (Exception e) {
			gm.sendPackets(new S_SystemMessage(".death キャラクター名 と入力して下さい。"));
		}
	}

	private void ress(L1PcInstance gm) {
		try {
			int objid = gm.getId();
			gm.sendPackets(new S_SkillSound(objid, 759));
			gm.broadcastPacket(new S_SkillSound(objid, 759));
			for (L1PcInstance pc : L1World.getInstance().getAllPlayers()) {
				if (pc.getCurrentHp() == 0 && pc.isDead()) {
					// 祝福された 復活スクロールと同じ効果
					pc.setTempID(objid);
					pc.sendPackets(new S_Message_YN(322, "")); // また復活したいですか？（Y/N）
				} else {

					pc.setCurrentHp(pc.getMaxHp());
					pc.setCurrentMp(pc.getMaxMp());
				}
			}
		} catch (Exception e) {
			gm.sendPackets(new S_SystemMessage(".ress コマンドエラー"));
		}
	}

	private void gmRoom(L1PcInstance gm, String room) {
		try {
			int i = 0;
			try {
				i = Integer.parseInt(room);
			} catch (NumberFormatException e) {
			}

			if (i == 1) {
				L1Teleport.teleport(gm, 32737, 32796, (short) 99, 5, false);
			} else if (i == 2) {
				L1Teleport.teleport(gm, 32734, 32799, (short) 17100, 5, false); // 17100!?
			} else if (i == 3) {
				L1Teleport.teleport(gm, 32644, 32955, (short) 0, 5, false);
			} else if (i == 4) {
				L1Teleport.teleport(gm, 33429, 32814, (short) 4, 5, false);
			} else if (i == 5) {
				L1Teleport.teleport(gm, 32894, 32535, (short) 300, 5, false);
			} else {
				L1Location loc = GMCommandsConfig.ROOMS.get(room.toLowerCase());
				if (loc == null) {
					gm.sendPackets(new S_SystemMessage(room + " 未定義のRoomです"));
					return;
				}
				L1Teleport.teleport(gm, loc.getX(), loc.getY(), (short) loc
						.getMapId(), 5, false);
			}
		} catch (Exception exception) {
			gm.sendPackets(new S_SystemMessage(
					".gmroom1～.gmroom5 or .gmroom name と入力して下さい。"));
		}
	}

	private void kick(L1PcInstance gm, String param) {
		try {
			L1PcInstance l1pcinstance1 = getPcForName(param);
			if (l1pcinstance1 != null) {
				gm.sendPackets(new S_SystemMessage((new StringBuilder())
						.append(l1pcinstance1.getName()).append("さんをキックしました。")
						.toString()));
				l1pcinstance1.sendPackets(new S_Disconnect());
			} else {
				gm.sendPackets(new S_SystemMessage(
						"そのような名前のキャラクターはワールド内には存在しません。"));
			}
		} catch (Exception e) {
			gm.sendPackets(new S_SystemMessage(".kick キャラクター名 と入力して下さい。"));
		}
	}

	private void skick(L1PcInstance gm, String param) {
		try {
			L1PcInstance target = getPcForName(param);
			if (target != null) {
				gm.sendPackets(new S_SystemMessage((new StringBuilder())
						.append(target.getName()).append("さんをキックしました。")
						.toString()));
				target.setX(33080);
				target.setY(33392);
				target.setMap((short) 4);
				target.sendPackets(new S_Disconnect());
				ClientThread targetClient = target.getNetConnection();
				targetClient.kick();
				_log.warning("GMのskickコマンドにより(" + targetClient.getAccountName()
						+ ":" + targetClient.getHostname() + ")との接続を強制切断しました。");
			} else {
				gm.sendPackets(new S_SystemMessage(
						"そのような名前のキャラクターはワールド内には存在しません。"));
			}
		} catch (Exception e) {
			gm.sendPackets(new S_SystemMessage(".kick キャラクター名 と入力して下さい。"));
		}
	}

	private void powerkick(L1PcInstance gm, String param) {
		try {
			L1PcInstance target = getPcForName(param);

			IpTable iptable = IpTable.getInstance();
			if (target != null) {
				iptable.banIp(target.getNetConnection().getIp()); // BANリストへIPを加える
				gm.sendPackets(new S_SystemMessage((new StringBuilder())
						.append(target.getName()).append("さんをキックしました。")
						.toString()));
				target.sendPackets(new S_Disconnect());
			} else {
				gm.sendPackets(new S_SystemMessage(
						"そのような名前のキャラクターはワールド内には存在しません。"));
			}
		} catch (Exception e) {
			gm.sendPackets(new S_SystemMessage(".powerkick キャラクター名 と入力して下さい。"));
		}
	}

	private void accbankick(L1PcInstance gm, String param) {
		try {
			L1PcInstance target = getPcForName(param);

			if (target != null) {
				// アカウントをBANする
				Account.ban(target.getAccountName());
				gm.sendPackets(new S_SystemMessage(target.getName()
						+ "さんをキックしました。"));
				target.sendPackets(new S_Disconnect());
			} else {
				gm.sendPackets(new S_SystemMessage(
						"そのような名前のキャラクターはワールド内には存在しません。"));
			}
		} catch (Exception e) {
			gm
					.sendPackets(new S_SystemMessage(
							".accbankick キャラクター名 と入力して下さい。"));
		}
	}

	private void burf(L1PcInstance gm, String param) {
		try {
			StringTokenizer stringtokenizer = new StringTokenizer(param);
			String s22 = stringtokenizer.nextToken();
			int i = Integer.parseInt(s22);

			for (L1PcInstance pc : L1World.getInstance().getAllPlayers()) {
				pc.sendPackets(new S_SkillSound(pc.getId(), i));
				pc.broadcastPacket(new S_SkillSound(pc.getId(), i));
			}
		} catch (Exception e) {
			gm.sendPackets(new S_SystemMessage(".burf castgfx と入力して下さい。"));
		}

	}

	private void buff(L1PcInstance gm, String args, boolean buffMe) {
		try {
			StringTokenizer tok = new StringTokenizer(args);
			int skillId = Integer.parseInt(tok.nextToken());
			int time = 0;
			if (tok.hasMoreTokens()) {
				time = Integer.parseInt(tok.nextToken());
			}

			L1Skills skill = SkillsTable.getInstance().getTemplate(skillId);

			ArrayList<L1PcInstance> players = new ArrayList<L1PcInstance>();
			if (buffMe) {
				players.add(gm);
			} else {
				players = L1World.getInstance().getVisiblePlayer(gm);
			}
			if (skill.getTarget().equals("buff")) {
				for (L1PcInstance pc : players) {
					new L1SkillUse().handleCommands(gm, skillId, pc.getId(), pc
							.getX(), pc.getY(), null, time,
							L1SkillUse.TYPE_SPELLSC);
				}
			} else if (skill.getTarget().equals("none")) {
				for (L1PcInstance pc : players) {
					new L1SkillUse().handleCommands(pc, skillId, pc.getId(), pc
							.getX(), pc.getY(), null, time,
							L1SkillUse.TYPE_GMBUFF);
				}
			} else {
				gm.sendPackets(new S_SystemMessage("buff系のスキルではありません。"));
			}
		} catch (Exception e) {
			gm.sendPackets(new S_SystemMessage(".buff skillId time と入力して下さい。"));
		}
	}

	private void mobspawn(L1PcInstance gm, int i, int randomrange,
			boolean isPineWand) {
		try {
			L1Npc l1npc = NpcTable.getInstance().getTemplate(i);
			if (l1npc != null) {
				Object obj = null;
				try {
					String s = l1npc.getImpl();
					Constructor constructor = Class.forName(
							"l1j.server.server.model.Instance." + s
									+ "Instance").getConstructors()[0];
					Object aobj[] = { l1npc };
					L1NpcInstance npc = (L1NpcInstance) constructor
							.newInstance(aobj);
					npc.setId(IdFactory.getInstance().nextId());
					npc.setMap(gm.getMapId());
					if (randomrange == 0) {
						if (gm.getHeading() == 0) {
							npc.setX(gm.getX());
							npc.setY(gm.getY() - 1);
						} else if (gm.getHeading() == 1) {
							npc.setX(gm.getX() + 1);
							npc.setY(gm.getY() - 1);
						} else if (gm.getHeading() == 2) {
							npc.setX(gm.getX() + 1);
							npc.setY(gm.getY());
						} else if (gm.getHeading() == 3) {
							npc.setX(gm.getX() + 1);
							npc.setY(gm.getY() + 1);
						} else if (gm.getHeading() == 4) {
							npc.setX(gm.getX());
							npc.setY(gm.getY() + 1);
						} else if (gm.getHeading() == 5) {
							npc.setX(gm.getX() - 1);
							npc.setY(gm.getY() + 1);
						} else if (gm.getHeading() == 6) {
							npc.setX(gm.getX() - 1);
							npc.setY(gm.getY());
						} else if (gm.getHeading() == 7) {
							npc.setX(gm.getX() - 1);
							npc.setY(gm.getY() - 1);
						}
					} else {
						int tryCount = 0;
						do {
							tryCount++;
							npc.setX(gm.getX()
									+ (int) (Math.random() * randomrange)
									- (int) (Math.random() * randomrange));
							npc.setY(gm.getY()
									+ (int) (Math.random() * randomrange)
									- (int) (Math.random() * randomrange));
							if (npc.getMap().isInMap(npc.getLocation())
									&& npc.getMap().isPassable(
											npc.getLocation())) {
								break;
							}
							Thread.sleep(1);
						} while (tryCount < 50);

						if (tryCount >= 50) {
							if (gm.getHeading() == 0) {
								npc.setX(gm.getX());
								npc.setY(gm.getY() - 1);
							} else if (gm.getHeading() == 1) {
								npc.setX(gm.getX() + 1);
								npc.setY(gm.getY() - 1);
							} else if (gm.getHeading() == 2) {
								npc.setX(gm.getX() + 1);
								npc.setY(gm.getY());
							} else if (gm.getHeading() == 3) {
								npc.setX(gm.getX() + 1);
								npc.setY(gm.getY() + 1);
							} else if (gm.getHeading() == 4) {
								npc.setX(gm.getX());
								npc.setY(gm.getY() + 1);
							} else if (gm.getHeading() == 5) {
								npc.setX(gm.getX() - 1);
								npc.setY(gm.getY() + 1);
							} else if (gm.getHeading() == 6) {
								npc.setX(gm.getX() - 1);
								npc.setY(gm.getY());
							} else if (gm.getHeading() == 7) {
								npc.setX(gm.getX() - 1);
								npc.setY(gm.getY() - 1);
							}
						}
					}

					npc.setHomeX(npc.getX());
					npc.setHomeY(npc.getY());
					npc.setHeading(gm.getHeading());

					L1World.getInstance().storeObject(npc);
					L1World.getInstance().addVisibleObject(npc);
					if (spawnTF == true) {
						L1Object object = L1World.getInstance().findObject(
								npc.getId());
						L1NpcInstance newnpc = (L1NpcInstance) object;
						newnpc.onNpcAI();
					}
					if (isPineWand) {
						L1NpcDeleteTimer timer = new L1NpcDeleteTimer(npc,
								300000);
						timer.begin();
					}
				} catch (Exception e) {
					_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
				}
			}
		} catch (Exception exception) {
		}
	}

	public void mobspawn(ClientThread client, int i, int randomrange,
			boolean isPineWand) {
		mobspawn(client.getActiveChar(), i, randomrange, isPineWand);
	}

	private void gfxId(L1PcInstance gm, String param) {
		try {
			StringTokenizer st = new StringTokenizer(param);
			int gfxid = Integer.parseInt(st.nextToken(), 10);
			int count = Integer.parseInt(st.nextToken(), 10);
			for (int i = 0; i < count; i++) {
				L1Npc l1npc = NpcTable.getInstance().getTemplate(45001);
				if (l1npc != null) {
					String s = l1npc.getImpl();
					Constructor constructor = Class.forName(
							"l1j.server.server.model.Instance." + s
									+ "Instance").getConstructors()[0];
					Object aobj[] = { l1npc };
					L1NpcInstance npc = (L1NpcInstance) constructor
							.newInstance(aobj);
					npc.setId(IdFactory.getInstance().nextId());
					npc.setGfxId(gfxid + i);
					npc.setNameId("");
					npc.setMap(gm.getMapId());
					npc.setX(gm.getX() + i * 2);
					npc.setY(gm.getY() + i * 2);
					npc.setHomeX(npc.getX());
					npc.setHomeY(npc.getY());
					npc.setHeading(4);

					L1World.getInstance().storeObject(npc);
					L1World.getInstance().addVisibleObject(npc);
				}
			}
		} catch (Exception exception) {
			gm.sendPackets(new S_SystemMessage(".gfxid id 出現させる数 と入力して下さい。"));
		}
	}

	private void invGfxId(L1PcInstance pc, String param) {
		try {
			StringTokenizer st = new StringTokenizer(param);
			int gfxid = Integer.parseInt(st.nextToken(), 10);
			int count = Integer.parseInt(st.nextToken(), 10);
			for (int i = 0; i < count; i++) {
				L1ItemInstance item = ItemTable.getInstance().createItem(40005);
				item.getItem().setGfxId(gfxid + i);
				item.getItem().setName(String.valueOf(gfxid + i));
				pc.getInventory().storeItem(item);
			}
		} catch (Exception exception) {
			pc
					.sendPackets(new S_SystemMessage(
							".invgfxid id 出現させる数 と入力して下さい。"));
		}
	}

	private void action(L1PcInstance pc, String param) {
		try {
			StringTokenizer st = new StringTokenizer(param);
			int actId = Integer.parseInt(st.nextToken(), 10);
			pc.sendPackets(new S_DoActionGFX(pc.getId(), actId));
		} catch (Exception exception) {
			pc.sendPackets(new S_SystemMessage(".action actid と入力して下さい。"));
		}
	}

	private void banIp(L1PcInstance gm, String param) {
		try {
			StringTokenizer stringtokenizer = new StringTokenizer(param);
			// IPを指定
			String s1 = stringtokenizer.nextToken();

			// add/delを指定(しなくてもOK)
			String s2 = null;
			try {
				s2 = stringtokenizer.nextToken();
			} catch (Exception e) {
			}

			IpTable iptable = IpTable.getInstance();
			boolean isBanned = iptable.isBannedIp(s1);

			for (L1PcInstance pc : L1World.getInstance().getAllPlayers()) {
				if (s1.equals(pc.getNetConnection().getIp())) {
					String msg = new StringBuilder().append("IP:").append(s1)
							.append(" で接続中のプレイヤー:").append(pc.getName())
							.toString();
					gm.sendPackets(new S_SystemMessage(msg));
				}
			}

			if ("add".equals(s2) && !isBanned) {
				iptable.banIp(s1); // BANリストへIPを加える
				String msg = new StringBuilder().append("IP:").append(s1)
						.append(" をBAN IPに登録しました。").toString();
				gm.sendPackets(new S_SystemMessage(msg));
			} else if ("del".equals(s2) && isBanned) {
				if (iptable.liftBanIp(s1)) { // BANリストからIPを削除する
					String msg = new StringBuilder().append("IP:").append(s1)
							.append(" をBAN IPから削除しました。").toString();
					gm.sendPackets(new S_SystemMessage(msg));
				}
			} else {
				// BANの確認
				if (isBanned) {
					String msg = new StringBuilder().append("IP:").append(s1)
							.append(" はBAN IPに登録されています。").toString();
					gm.sendPackets(new S_SystemMessage(msg));
				} else {
					String msg = new StringBuilder().append("IP:").append(s1)
							.append(" はBAN IPに登録されていません。").toString();
					gm.sendPackets(new S_SystemMessage(msg));
				}
			}
		} catch (Exception e) {
			gm.sendPackets(new S_SystemMessage(
					".banip IP [ add | del ]と入力して下さい。"));
		}
	}

	private void who(L1PcInstance gm, String param) {
		try {
			Collection<L1PcInstance> players = L1World.getInstance()
					.getAllPlayers();
			String amount = String.valueOf(players.size());
			S_WhoAmount s_whoamount = new S_WhoAmount(amount);
			gm.sendPackets(s_whoamount);

			// オンラインのプレイヤーリストを表示
			if (param.equalsIgnoreCase("all")) {
				gm.sendPackets(new S_SystemMessage("-- オンラインのプレイヤー --"));
				StringBuffer buf = new StringBuffer();
				for (L1PcInstance each : players) {
					buf.append(each.getName());
					buf.append(" / ");
					if (buf.length() > 50) {
						gm.sendPackets(new S_SystemMessage(buf.toString()));
						buf.delete(0, buf.length() - 1);
					}
				}
				if (buf.length() > 0) {
					gm.sendPackets(new S_SystemMessage(buf.toString()));
				}
			}
		} catch (Exception e) {
			gm.sendPackets(new S_SystemMessage(".who [all] と入力して下さい。"));
		}
	}

	private L1PcInstance getPcForName(String name) {
		L1PcInstance pc = L1World.getInstance().getPlayer(name);
		if (pc == null) {
			for (L1PcInstance player : L1World.getInstance().getAllPlayers()) {
				if (player.getName().toLowerCase().equals(name.toLowerCase())) {
					pc = player;
					break;
				}
			}
		}
		return pc;
	}

	private void describe(L1PcInstance gm) {
		try {
			StringBuilder msg = new StringBuilder();
			gm.sendPackets(new S_SystemMessage("-- describe: " + gm.getName()
					+ " --"));
			int hpr = gm.getHpr() + gm.getInventory().hpRegenPerTick();
			int mpr = gm.getMpr() + gm.getInventory().mpRegenPerTick();
			msg.append("Dmg: +" + gm.getDmgup() + " / ");
			msg.append("Hit: +" + gm.getHitup() + " / ");
			msg.append("MR: " + gm.getMr() + " / ");
			msg.append("HPR: " + hpr + " / ");
			msg.append("MPR: " + mpr + " / ");
			msg.append("Karma: " + gm.getKarma() + " / ");
			msg.append("Item: " + gm.getInventory().getSize() + " / ");
			gm.sendPackets(new S_SystemMessage(msg.toString()));
		} catch (Exception e) {
			gm.sendPackets(new S_SystemMessage(".desc コマンドエラー"));
		}
	}

	public static boolean isHpBarTarget(L1Object obj) {
		if (obj instanceof L1MonsterInstance) {
			return true;
		}
		if (obj instanceof L1PcInstance) {
			return true;
		}
		if (obj instanceof L1SummonInstance) {
			return true;
		}
		if (obj instanceof L1PetInstance) {
			return true;
		}
		return false;
	}

	private void hpBar(L1PcInstance gm, String param) {
		if (param.equalsIgnoreCase("on")) {
			gm.setSkillEffect(L1SkillId.GMSTATUS_HPBAR, 0);
		} else if (param.equalsIgnoreCase("off")) {
			gm.removeSkillEffect(L1SkillId.GMSTATUS_HPBAR);

			for (L1Object obj : gm.getKnownObjects()) {
				if (isHpBarTarget(obj)) {
					gm.sendPackets(new S_HPMeter(obj.getId(), 0xFF));
				}
			}
		} else {
			gm.sendPackets(new S_SystemMessage(".hpbar on|off と入力してください。"));
		}
	}

	private void reloadTraps() {
		L1WorldTraps.reloadTraps();
	}

	private void showTraps(L1PcInstance gm, String param) {
		if (param.equalsIgnoreCase("on")) {
			gm.setSkillEffect(L1SkillId.GMSTATUS_SHOWTRAPS, 0);
		} else if (param.equalsIgnoreCase("off")) {
			gm.removeSkillEffect(L1SkillId.GMSTATUS_SHOWTRAPS);

			for (L1Object obj : gm.getKnownObjects()) {
				if (obj instanceof L1TrapInstance) {
					gm.removeKnownObject(obj);
					gm.sendPackets(new S_DeleteNewObject(obj));
				}
			}
		} else {
			gm.sendPackets(new S_SystemMessage(".showtrap on|off と入力してください。"));
		}
	}

	private String _lastCmd = "";

	private void redo(L1PcInstance gm, String param) {
		try {
			if (_lastCmd.isEmpty()) {
				gm.sendPackets(new S_SystemMessage("記憶しているコマンドがありません"));
				return;
			}
			if (param.isEmpty()) {
				gm.sendPackets(new S_SystemMessage("コマンド " + _lastCmd
						+ " を再実行します"));
				handleCommands(gm, _lastCmd);
			} else {
				// 引数を変えて実行
				StringTokenizer token = new StringTokenizer(_lastCmd);
				String cmd = token.nextToken() + " " + param;
				gm.sendPackets(new S_SystemMessage("コマンド " + cmd + " を実行します。"));
				handleCommands(gm, cmd);
			}
		} catch (Exception e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
			gm.sendPackets(new S_SystemMessage(".r コマンドエラー"));
		}
	}

	private String _faviCom = "";

	private void favorite(L1PcInstance gm, String param) {
		try {
			if (param.startsWith("set")) {
				// コマンドの登録
				StringTokenizer st = new StringTokenizer(param);
				st.nextToken();
				if (!st.hasMoreTokens()) {
					gm.sendPackets(new S_SystemMessage("コマンドが空です。"));
					return;
				}
				StringBuilder cmd = new StringBuilder();
				String temp = st.nextToken(); // コマンドタイプ
				if (temp.equalsIgnoreCase("f")) {
					gm.sendPackets(new S_SystemMessage("f 自身は登録できません。"));
					return;
				}
				cmd.append(temp + " ");
				while (st.hasMoreTokens()) {
					cmd.append(st.nextToken() + " ");
				}
				_faviCom = cmd.toString().trim();
				gm.sendPackets(new S_SystemMessage(_faviCom + " を登録しました。"));
			} else if (param.startsWith("show")) {
				gm.sendPackets(new S_SystemMessage("現在の登録コマンド: " + _faviCom));
			} else if (_faviCom.isEmpty()) {
				gm.sendPackets(new S_SystemMessage("登録しているコマンドがありません。"));
			} else {
				StringBuilder cmd = new StringBuilder();
				StringTokenizer st = new StringTokenizer(param);
				StringTokenizer st2 = new StringTokenizer(_faviCom);
				while (st2.hasMoreTokens()) {
					String temp = st2.nextToken();
					if (temp.startsWith("%")) {
						cmd.append(st.nextToken() + " ");
					} else {
						cmd.append(temp + " ");
					}
				}
				while (st.hasMoreTokens()) {
					cmd.append(st.nextToken() + " ");
				}
				gm.sendPackets(new S_SystemMessage(cmd + " を実行します。"));
				handleCommands(gm, cmd.toString());
			}
		} catch (Exception e) {
			gm.sendPackets(new S_SystemMessage(".f set コマンド名 "
					+ "| .f show | .f [引数] と入力してください。"));
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
		}
	}
}
